using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;
using System.Xml;
using System.Net;
using System.Web;

namespace GMailNotifierNET.Classes.GMailFeed
{
    public class GMailFeed
    {
        private ReadOnlyCollection<GMailFeedItem> m_gmailFeedItems;
        private string m_sTitle = null;
        private string m_sTagLine = null;
        private GMailFeedLink m_gmailLink = null;
        private DateTime m_datModified = DateTime.MinValue;


        public GMailFeed(Uri urlFeed, string username, string password)
        {
            List<GMailFeedItem> feedItems = new List<GMailFeedItem>();

            XmlReaderSettings xmlSettings = new XmlReaderSettings();

            XmlUrlResolver xmlResolver = new XmlUrlResolver();
            xmlResolver.Credentials = new NetworkCredential(username, password);

            xmlSettings.XmlResolver = xmlResolver;

            XmlReader xmlReader = XmlTextReader.Create(
                urlFeed.ToString(),
                xmlSettings);
            
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load(xmlReader);

            foreach (XmlNode xmlNode in xmlDocument.ChildNodes)
            {
                if (xmlNode.Name == "feed")
                {
                    foreach (XmlNode feedNode in xmlNode.ChildNodes)
                    {
                        switch(feedNode.Name)
                        {
                            case "title":
                                this.m_sTitle = feedNode.InnerText;
                                break;

                            case "tagline":
                                this.m_sTagLine = feedNode.InnerText;
                                break;

                            case "link":
                                this.m_gmailLink = new GMailFeedLink(
                                    feedNode.Attributes["rel"].InnerText, 
                                    feedNode.Attributes["href"].InnerText, 
                                    feedNode.Attributes["type"].InnerText);
                                break;

                            case "modified":
                                DateTime.TryParse(feedNode.InnerText, out this.m_datModified);
                                break;

                            case "entry":
                                string title = null;
                                string summary = null;
                                GMailFeedLink gmailLink = null;
                                DateTime modified = DateTime.MinValue;
                                DateTime issued = DateTime.MinValue;
                                string id = null;
                                GMailAuthor gmailAuthor = null;
                                
                                foreach (XmlNode entryNode in feedNode.ChildNodes)
                                {
                                    switch (entryNode.Name)
                                    { 
                                        case "title":
                                            title = entryNode.InnerText;
                                            break;

                                        case "summary":
                                            summary = HttpUtility.HtmlDecode(entryNode.InnerText);
                                            break;

                                        case "link":
                                            gmailLink = new GMailFeedLink(
                                                entryNode.Attributes["rel"].InnerText,
                                                entryNode.Attributes["href"].InnerText,
                                                entryNode.Attributes["type"].InnerText);
                                            break;

                                        case "modified":
                                            DateTime.TryParse(entryNode.InnerText, out modified);
                                            break;

                                        case "issued":
                                            DateTime.TryParse(entryNode.InnerText, out issued);
                                            break;

                                        case "id":
                                            id = entryNode.InnerText;
                                            break;

                                        case "author":
                                            string name = null;
                                            string email = null;

                                            foreach(XmlNode authorNode in entryNode.ChildNodes)
                                            {
                                                switch (authorNode.Name)
                                                { 
                                                    case "name":
                                                        name = authorNode.InnerText;
                                                        break;

                                                    case "email":
                                                        email = authorNode.InnerText;
                                                        break;
                                                }
                                            }

                                            gmailAuthor = new GMailAuthor(
                                                name,
                                                email);

                                            break;                                    
                                    }
                                }

                                GMailFeedItem gmailFeedItem = new GMailFeedItem(
                                    title,
                                    summary,
                                    gmailLink,
                                    modified,
                                    issued,
                                    id,
                                    gmailAuthor);

                                feedItems.Add(gmailFeedItem);

                                break;
                        }

                    }
                }
            }

            this.m_gmailFeedItems = new ReadOnlyCollection<GMailFeedItem>(feedItems);            
        }

        public override bool Equals(object obj)
        {
            bool equalFeed = true;

            GMailFeed castedFeed = (GMailFeed)obj;

            if (this.m_gmailFeedItems.Count == castedFeed.FeedItems.Count)
            {
                for (int i = 0; i < this.m_gmailFeedItems.Count; i++)
                {
                    if (this.m_gmailFeedItems[i].ID != castedFeed.m_gmailFeedItems[i].ID)
                    {
                        equalFeed = false;
                        break;
                    }
                }
            }
            else
                equalFeed = false;

            return equalFeed;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        private DateTime ConvertFeedTimeToDateTime(string feedTime)
        {
            return DateTime.MinValue;
        }

        public string Title
        {
            get { return this.m_sTitle; }
        }

        public string TagLine
        {
            get { return this.m_sTagLine; }
        }

        public GMailFeedLink Link
        {
            get { return this.m_gmailLink; }
        }

        public DateTime Modified
        {
            get { return this.m_datModified; }
        }

        public ReadOnlyCollection<GMailFeedItem> FeedItems
        {
            get { return this.m_gmailFeedItems; }
        }
    }
}
